﻿using System.Collections;
using System.Globalization;
using System.Text;
using System.Xml;
using Newtonsoft.Json;
using System.Data;
using System.IO;
using Org.EasyWeb.Common;
using System;

public sealed class XmlToJSONParser
{
    private static void OutputNode(string childname, object alChild, StringBuilder sbJSON, bool showNodeName)
    {
        if (alChild == null)
        {
            if (showNodeName)
            {
                sbJSON.Append(SafeJSON(childname) + ": ");
            }
            sbJSON.Append("null");
        }
        else if (alChild is string)
        {
            if (showNodeName)
            {
                sbJSON.Append(SafeJSON(childname) + ": ");
            }

            string s = (string)alChild;

            s = s.Trim();

            sbJSON.Append(SafeJSON(s));
        }
        else
        {
            XmlToJSONnode(sbJSON, (XmlElement)alChild, showNodeName);
        }

        sbJSON.Append(", ");

    }

    public static string SafeJSON(string s)
    {

        if ((s == null) || (s.Length == 0))
        {

            return "\"\"";

        }

        int length = s.Length;

        StringBuilder builder = new StringBuilder(length + 4);

        builder.Append('"');

        for (int i = 0; i < length; i++)
        {

            char ch = s[i];

            switch (ch)
            {

                case '\\':

                case '"':

                case '>':

                    builder.Append('\\');

                    builder.Append(ch);

                    break;

                case '\b':

                    builder.Append(@"\b");

                    break;
                case '\t':

                    builder.Append(@"\t");

                    break;

                case '\n':

                    builder.Append(@"\n");

                    break;
                case '\f':

                    builder.Append(@"\f");

                    break;


                case '\r':

                    builder.Append(@"\r");

                    break;

                default:

                    if (ch < ' ')
                    {
                        string str2 = new string(ch, 1);

                        string str = "000" + int.Parse(str2, NumberStyles.HexNumber);

                        builder.Append(@"\u" + str.Substring(str.Length - 4));
                    }

                    else
                    {
                        builder.Append(ch);
                    }
                    break;

            }

        }

        builder.Append('"');

        return builder.ToString();

    }

    private static void StoreChildNode(IDictionary childNodeNames, string nodeName, object nodeValue)
    {

        ArrayList list2;

        if (nodeValue is XmlElement)
        {

            XmlNode node = (XmlNode)nodeValue;

            if (node.Attributes.Count == 0)
            {

                XmlNodeList childNodes = node.ChildNodes;

                if (childNodes.Count == 0)
                {

                    nodeValue = null;

                }

                else if ((childNodes.Count == 1) && (childNodes[0] is XmlText))
                {

                    nodeValue = childNodes[0].InnerText;

                }

            }

        }

        object obj2 = childNodeNames[nodeName];

        if (obj2 == null)
        {

            list2 = new ArrayList();

            childNodeNames[nodeName] = list2;

        }

        else
        {

            list2 = (ArrayList)obj2;

        }

        list2.Add(nodeValue);

    }

    public static string XmlToJSON(XmlDocument xmlDoc)
    {

        StringBuilder sbJSON = new StringBuilder();

        sbJSON.Append("{ ");

        XmlToJSONnode(sbJSON, xmlDoc.DocumentElement, true);

        sbJSON.Append("}");

        return sbJSON.ToString();

    }

    private static void XmlToJSONnode(StringBuilder sbJSON, XmlNode node, bool showNodeName)
    {
        if (showNodeName)
        {

            sbJSON.Append(node.Name + ": ");

        }

        sbJSON.Append("{");

        SortedList childNodeNames = new SortedList();

        if (node.Attributes != null)
        {

            foreach (XmlAttribute attribute in node.Attributes)
            {

                StoreChildNode(childNodeNames, attribute.Name, attribute.InnerText);

            }

        }

        foreach (XmlNode node2 in node.ChildNodes)
        {

            if (node2 is XmlText)
            {

                StoreChildNode(childNodeNames, "value", node2.InnerText);

            }

            else if (node2 is XmlElement)
            {

                StoreChildNode(childNodeNames, node2.Name, node2);

            }

        }

        foreach (string str in childNodeNames.Keys)
        {

            ArrayList list2 = (ArrayList)childNodeNames[str];

            if (list2.Count == 1)
            {
                OutputNode(str, list2[0], sbJSON, true);
            }
            else
            {
                sbJSON.Append(str + ": [ ");

                foreach (object obj2 in list2)
                {
                    OutputNode(str, obj2, sbJSON, false);
                }

                sbJSON.Remove(sbJSON.Length - 2, 2);

                sbJSON.Append(" ], ");

            }
        }

        sbJSON.Remove(sbJSON.Length - 2, 2);

        sbJSON.Append(" }");

    }

    public static string DataSetToJSON(DataSet ds)
    {
        return DataSetToJSON(ds, false);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="ds"></param>
    /// <param name="FormatJsonOutput"></param>
    /// <returns></returns>
    public static string DataSetToJSON(DataSet ds, bool FormatJsonOutput)
    {
        return Serialize(ds, FormatJsonOutput);
    }

    public static string DataSetToJSON(DataTable table)
    {
        return DataTableToJSON(table, false);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="table"></param>
    /// <param name="FormatJsonOutput"></param>
    /// <returns></returns>
    public static string DataTableToJSON(DataTable table, bool FormatJsonOutput)
    {
        return Serialize(table, FormatJsonOutput);
    }

    private static string Serialize(object value, bool FormatJsonOutput)
    {
        Type type = value.GetType();

        JsonSerializer json = new JsonSerializer();

        json.NullValueHandling = NullValueHandling.Ignore;

        json.ObjectCreationHandling = ObjectCreationHandling.Replace;
        json.MissingMemberHandling = MissingMemberHandling.Ignore;
        json.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

        if (type == typeof(DataTable))
            json.Converters.Add(new DataTableConverter());
        else if (type == typeof(DataSet))
            json.Converters.Add(new DataSetConverter());

        StringWriter sw = new StringWriter();
        Newtonsoft.Json.JsonTextWriter writer = new JsonTextWriter(sw);

        if (FormatJsonOutput)
            writer.Formatting = Newtonsoft.Json.Formatting.Indented;
        else
            writer.Formatting = Newtonsoft.Json.Formatting.None;

        writer.QuoteChar = '"';
        json.Serialize(writer, value);

        string output = sw.ToString();
        writer.Close();
        sw.Close();

        return output;
    }
}
